package com.wangwenjun.concurrency.chapter14.blockingqueue;

import org.junit.Test;

import java.util.Comparator;
import java.util.Queue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @Package: com.wangwenjun.concurrency.chapter14.blockingqueue
 * @ClassName: UsePriorityBlockingQueue
 * @Author: lujieni
 * @Description: 1
 * @Date: 2021-03-10 16:07
 * @Version: 1.0
 *
 *  PriorityBlockingQueue
 *  1.无界
 *  2.按照优先级排列
 *  3.线程安全
 *  4.因为无界任何向队列中添加元素的方法都不会阻塞
 *  5.元素必须实现Comparable接口或者提供Comparator比较器
 *
 */
public class UsePriorityBlockingQueue {

    /**
     *
     * add方法超过队列容量会直接扩容
     *
     */
    @Test
    public void testAdd(){
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);

        System.out.println(blockingQueue.add(1));
        System.out.println(blockingQueue.add(2));
        System.out.println(blockingQueue.add(3));
        System.out.println(blockingQueue.add(4));
    }

    /**
     * remove如果队列为空会抛异常
     */
    @Test
    public void testRemove(){
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);

        System.out.println(blockingQueue.add(1));
        System.out.println(blockingQueue.add(2));
        System.out.println(blockingQueue.add(3));

        blockingQueue.remove();
        blockingQueue.remove();
        blockingQueue.remove();
        blockingQueue.remove();

    }

    /**
     * offer方法永远返回true因为是无界队列
     */
    @Test
    public void testOffer(){
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));
        System.out.println(blockingQueue.offer(4));
    }

    /**
     * poll队列为空会返回null, 不会抛异常
     */
    @Test
    public void testPoll(){
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
        System.out.println(blockingQueue.poll());
    }

    /**
     * put方法永远不会阻塞因为是无界队列
     */
    @Test
    public void testPut(){
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);
        blockingQueue.put(4);
    }

    /**
     * 会阻塞
     * @throws InterruptedException
     */
    @Test
    public void testTake() throws InterruptedException {
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);
        blockingQueue.put(1);
        blockingQueue.put(2);
        blockingQueue.put(3);


        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
        blockingQueue.take();
    }


    /**
     * Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
     * Returns:
     * the head of this queue, or null if this queue is empty
     *
     * peek只看队首元素是啥但不移除元素,如果队列为空返回null
     */
    @Test
    public void testPeek(){
        PriorityBlockingQueue<Integer> blockingQueue = new PriorityBlockingQueue<>(3);

        System.out.println(blockingQueue.offer(1));
        System.out.println(blockingQueue.offer(2));
        System.out.println(blockingQueue.offer(3));

        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
        System.out.println(blockingQueue.peek());
    }

    @Test
    public void testStudent(){
        PriorityBlockingQueue<Student> blockingQueue = new PriorityBlockingQueue<>(3);
        blockingQueue.add(new Student(10));
        blockingQueue.add(new Student(100));
        System.out.println(blockingQueue.poll().importance);
    }


    private class Student implements Comparable<Student>{
        private int importance;
        @Override
        public int compareTo(Student o) {
            return o.importance - this.importance;
        }

        public Student(int importance) {
            this.importance = importance;
        }
    }
}